package kom;

import java.awt.Rectangle;
import kom.GameTimer.GameTask;
import kom.sound.Audio;

public abstract class LivingEntity extends Entity {

    protected boolean canJump = true;
    protected float maxJump = 7f;
    protected float jumpHeight = 0;
    protected float jumpSpeed = 4f;
    protected boolean jumping = false;
    protected boolean stunned = false;
    protected int facing = Map.DIR_RIGHT;
    protected int direction = 0;
    protected int ticksToAnimate = 5;
    protected int tickAnim = 0;
    protected int sprite = 0;
    protected int maxFrame = 3;
    protected int frame = 0;

    public LivingEntity(int x, int y) {
        box = new Rectangle(x, x, 8, 8);
        this.x = x;
        this.y = y;
    }

    // gets the future bouding box of that player
    public Rectangle getFutureBox() {
        return new Rectangle((int) (x + 2 + aceleration.x), (int) (y + 3 + aceleration.y), 12, 16);
    }

    public boolean isMoving() {
        if(aceleration.x ==0 && aceleration.y ==0) {
            return false;
        }
        return true;
    }
    
    public void gravityTick() {
        // a boolean let me know when i need to fall or not
        // this is set in map, withc knows the tiles under its feet
        if (applyGravity && !jumping) {
            float aceY = aceleration.y;
            if(aceY <  10f) {
                aceY += 0.8f;
            }
            aceleration.y = aceY;
        } else {
            if(jumping) {
                aceleration.y = -jumpSpeed;
                jumpHeight += jumpSpeed;
                if(jumpHeight > 16) {
                    jumping = false;
                    canJump = false;
                    applyGravity = true;
                }
            }
            else{
                aceleration.y = 0;
                jumpHeight = 0;
                canJump = true;
            }
        }
    }
    
    public void hitWall(int wallDirection) {
        if (!stunned) {
            if (wallDirection == Map.DIR_UP) {
                aceleration.x = 0;
                aceleration.y = 0.1f;
            } else if ((aceleration.x > 0 &&aceleration.x > 3) || (aceleration.x < 0 && aceleration.x <-3)) {
                Audio.playSound("hitwall2");
                stunned = true;
                // apply a little knockback
                aceleration.x = -aceleration.x/4;
                if(!jumping && !applyGravity) {
                    aceleration.y = -3.5f;
                }
                jumping=false;
                canJump = false;
                applyGravity = true;
                frame = 4;
                // timers for that little stun 
                GameTask task = new GameTask(100) {

                    @Override
                    public void run() {
                        GameTask t =new GameTask(400) {

                            @Override
                            public void run() {
                               stunned = false;
                            }
                            
                        };
                        Kom.timer.addTask(t);
                        
                        frame = 5;
                    }
                };
                Kom.timer.addTask(task);
            } else {
                aceleration.x = 0;
            }
        }
    }
    
    // changes the aceleration towards my speed, but will not move the
    // entity yet
    public void calculateNextPosition() {
        if(stunned) {
            return;
        }
          // acelerates the entity to the direction its moving to
        if (direction == Map.DIR_RIGHT) {
            float aceX = aceleration.x;
            if (aceX < 0) {
                if (aceX < this.maxSpeed) {
                    if(isInAir()) {
                        aceX += desacelerationSpeed;
                    }
                    else {
                        aceX += desacelerationSpeed * 1.5;
                    }
                }
                if (aceX > maxSpeed) {
                    aceX = maxSpeed;
                }
                aceleration.x = aceX;
            } else {
                if (aceX < this.maxSpeed) {
                    aceX += acelerationSpeed;
                }
                if (aceX > maxSpeed) {
                    aceX = maxSpeed;
                }
                aceleration.x = aceX;
            }
        } else if (direction == Map.DIR_LEFT) {
            float aceX = aceleration.x;
            if (aceX > 0) {
                if (aceX > this.maxSpeed * -1) {
                    if(isInAir()) { 
                        aceX -= desacelerationSpeed;
                    }
                        else {
                        aceX -= desacelerationSpeed * 1.5;
                    }
                }
                if (aceX < maxSpeed * -1) {
                    aceX = maxSpeed * -1;
                }
                aceleration.x = aceX;
            } else {
                if (aceX > this.maxSpeed * -1) {
                    aceX -= acelerationSpeed;
                }
                if (aceX < maxSpeed * -1) {
                    aceX = maxSpeed * -1;
                }
                aceleration.x = aceX;
            }
            // nothing pressed, we deacelerate
        } else if (direction == Map.DIR_NONE) {
            if (aceleration.x > 0) {
                if (aceleration.x - desacelerationSpeed < 0) {
                    aceleration.x = 0;
                } else {
                    aceleration.x -= desacelerationSpeed;
                }
            } else if (aceleration.x + desacelerationSpeed > 0) {
                aceleration.x = 0;
            } else {
                aceleration.x += desacelerationSpeed;
            }
        }
    }
    
    public abstract void tick();

    public boolean isCanJump() {
        return canJump;
    }

    public void setCanJump(boolean canJump) {
        this.canJump = canJump;
    }

    public int getDirection() {
        return direction;
    }
    
    public void setDirection(int direction) {
        if(direction!=Map.DIR_NONE) {
            if(!isInAir()) {
                if(this.direction!=this.facing) {
                    this.facing = this.direction;
                }
            }
        }
        this.direction = direction;
        
        
    }

    public int getFacing() {
        return facing;
    }

    public void setFacing(int facing) {
        this.facing = facing;
    }

    public int getFrame() {
        return frame;
    }

    public void setFrame(int frame) {
        this.frame = frame;
    }

    public float getJumpHeight() {
        return jumpHeight;
    }

    public void setJumpHeight(float jumpHeight) {
        this.jumpHeight = jumpHeight;
    }

    public float getJumpSpeed() {
        return jumpSpeed;
    }

    public void setJumpSpeed(float jumpSpeed) {
        this.jumpSpeed = jumpSpeed;
    }

    public boolean isJumping() {
        return jumping;
    }

    public void setJumping(boolean jumping) {
        this.jumping = jumping;
    }

    public int getMaxFrame() {
        return maxFrame;
    }

    public void setMaxFrame(int maxFrame) {
        this.maxFrame = maxFrame;
    }

    public float getMaxJump() {
        return maxJump;
    }

    public void setMaxJump(float maxJump) {
        this.maxJump = maxJump;
    }

    public int getSprite() {
        return sprite;
    }

    public void setSprite(int sprite) {
        this.sprite = sprite;
    }

    public boolean isStunned() {
        return stunned;
    }

    public void setStunned(boolean stunned) {
        this.stunned = stunned;
    }

    public int getTickAnim() {
        return tickAnim;
    }

    public void setTickAnim(int tickAnim) {
        this.tickAnim = tickAnim;
    }

    public int getTicksToAnimate() {
        return ticksToAnimate;
    }

    public void setTicksToAnimate(int ticksToAnimate) {
        this.ticksToAnimate = ticksToAnimate;
    }
    
    
}

